在 Ruby 的世界裡,你可以使用 Module#alias_method 幫方法取一個新的別名。從 Ruby 的官方文件可以得知 :
alias_method(new_name, old_name)
Makes new_name a new copy of the method old_name. This can be used to retain access to methods that are overridden.
alias_method() 的第一個參數是『新的方法名稱』,第二個參數是『舊的方法名稱』。參數可用符號(symbol)或是字串(string)表示。
class MyClass
def my_method;
"my_method()"
end
alias_method :m, :my_method
end
obj = MyClass.new
obj.my_method # => "my_method()"
obj.m # => "my_method()"
建立方法的新別名,可以保留原有方法的功能,同時可依需求來改寫方法並命名更適合的新名稱。
class String
alias_method :real_length, :length
def length
real_length > 5 ? "long" : "short"
end
end
"How are you".length # => "long"
"How are you".real_length # => 11
以上面的範例來說:我們重新定義的 String#length(),但是 real_length()仍然可以參照原始的 length() 方法。其實當重新定義方法時,實際上並不是直接改變方法,而是定義了一個新方法,接著把現有的方法名稱連接上去而已。只要ㄧ直有別名連接該方法,舊版本的方法就可以被呼叫。
Around Alias 也是Ruby 黑魔法之一,可以被解析成以下三個步驟:
其中一個有關於 Around Alias 的缺點就是當方法被重新定義過後,原本的舊方法有可能其他人更改變動,而造成不必要的誤解。因此你可以幫方法取別名後,再將原本的舊方法改為私有方法,就可以避免掉這個問題。
class String
alias_method :real_length, :length
def length
real_length > 5 ? "long" : "short"
end
private :real_length
end
"War and Peace".length # => "long"
"War and Peace".send(:real_length) # => "13"
"War and Peace".real_length # => private method… (NoMethodError)
另ㄧ個比較大的問題是 Around Aliases 其實也是ㄧ種形式上的 Monkey patch,這代表著因為方法被重新定義過了,有可能造成與之前撰寫好的程式碼產生衝突。
明天將介紹 另一個 Ruby 的黑魔法 Refinement,將可以解決 Monkey patch 可能產生的問題。